package org.xurui.bsj.protocol.msg;

import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import org.jetlinks.core.message.codec.EncodedMessage;
import org.jetlinks.core.message.function.FunctionInvokeMessage;
import org.jetlinks.core.message.property.WritePropertyMessage;
import org.springframework.util.StringUtils;
import org.xurui.bsj.protocol.cache.ConcurrentMapCache;
import org.xurui.bsj.protocol.utils.AESUtil;
import org.xurui.bsj.protocol.utils.AesUtils;
import sun.misc.BASE64Decoder;

import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;


@Slf4j
public class BsjMessageBuilder {

    private static byte[] aesKey =  {(byte)0x96, (byte)0xB6, (byte)0x71, (byte)0x5E, (byte)0xF5, (byte)0x0F, (byte)0xA4, (byte)0x55,
        (byte)0x7F, (byte)0x6C, (byte)0xF9, (byte)0x77, (byte)0x17, (byte)0x8E, (byte)0x86, (byte)0xC9};
    private static byte[] aesIv =  {(byte)0x11,(byte) 0xC5, (byte)0x00,(byte) 0x74, (byte)0x0B,(byte) 0xE4, (byte)0x4D, (byte)0x4E,
        (byte) 0xE5,(byte) 0xBD,(byte) 0xAE,(byte) 0xD0, (byte)0x3C,(byte) 0xE7, (byte)0x6F, (byte)0xFF};
    private static byte[] paddingArr = {(byte)0x00,(byte)0x01,(byte)0x02,(byte)0x03,(byte)0x04,(byte)0x05,(byte)0x06,(byte)0x07,
        (byte)0x08, (byte)0x09,(byte)0x0A,(byte)0x0B,(byte)0x0C,(byte)0x0D,(byte)0x0E,(byte)0x0F};
    private static String tagAndVersion = "#kdsjafjalsdjg#170";
    private static String suffix = "\r\n";
    private static AtomicInteger flow = new AtomicInteger();

    public static BsjMessageBuilder create() {
        return new BsjMessageBuilder();
    }

    public  BsjMessage buildBsjMessage(String message){
        if(StringUtils.isEmpty(message)){
            log.error("博实结上报消息为空");
            return null;
        }
        BsjMessage msg = new BsjMessage();
        try{

            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] content =  base64Decoder.decodeBuffer(message);
            int plaintextLength = content.length;
            int blockSize = 16;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(content, 0, plaintext, 0, content.length);
            //解密消息体
            message = new String(AESUtil.aes128Cbc(aesKey,aesIv,plaintext,false ),"UTF8");
            message = message.split("\\[")[1].split("]")[0].trim();
            String[] msgArr = message.split(",");
            msg.getHeader().setBeginMark("[");
            msg.getHeader().setDeviceNo(msgArr[0]);
            msg.getHeader().setIccid(msgArr[1]);
            msg.getHeader().setOrderNo(msgArr[2]);
            msg.getHeader().setCmd(msgArr[3]);
            msg.getHeader().setType(Integer.parseInt(msgArr[4]));
            msg.getHeader().setMsgTime(msgArr[5]);
            msg.getHeader().setLength(Integer.parseInt(msgArr[6]));
            String tempBody = msgArr[7];
            msg.setTempBody(StringUtils.isEmpty(tempBody)?"":tempBody);
        }catch(Exception e){
            log.error("解析博实结上报消息头异常",e);
            return null;
        }
        return msg;
    }

    public EncodedMessage bulidBsjCommonReplyMessage(BsjMessage bsjMessage){
        try {
            StringBuffer sb = new StringBuffer();
            SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMddHHmmss");
            String currentTimeMillls=dateFormat.format(System.currentTimeMillis());
            sb.append(bsjMessage.getHeader().getBeginMark())
                .append(bsjMessage.getHeader().getDeviceNo())
                .append(",")
                .append(bsjMessage.getHeader().getIccid())
                .append(",")
                .append(bsjMessage.getHeader().getOrderNo())
                .append(",")
                .append(bsjMessage.getHeader().getCmd())
                .append(",")
                .append(bsjMessage.getHeader().getType()==3?4:bsjMessage.getHeader().getType())
                .append(",")
                .append(currentTimeMillls)
                .append(",")
                .append(bsjMessage.getTempReplyBody().length())
                .append(",")
                .append(bsjMessage.getTempReplyBody())
                .append(bsjMessage.getEndMark());
            byte[] content = sb.toString().getBytes("utf-8");
            log.debug("博实结平台下发消息-{}",sb.toString());
            //加密消息
            String encodedText = AesUtils.aes128CbcEncrypt(aesKey,aesIv,content);
            String result = encodedText.replaceAll("[\\s*\t\n\r]", "")+tagAndVersion+suffix;
            return EncodedMessage
                .simple(Unpooled.wrappedBuffer(result.getBytes()));
        }catch (Exception e){
            log.error("回复博实结消息加密异常",e);
        }
        return null;
    }

    public EncodedMessage buildBsjFunctionInvoickMessage(FunctionInvokeMessage message,String body){
        BsjMessage msg = new BsjMessage();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMddHHmmss");
        String currentTimeMillls=dateFormat.format(System.currentTimeMillis());
        msg.getHeader().setBeginMark("[");
        msg.getHeader().setDeviceNo(message.getDeviceId());
        msg.getHeader().setIccid(message.getCode());
        msg.getHeader().setOrderNo(flowNo());
        msg.getHeader().setCmd(message.getFunctionId());
        msg.getHeader().setType(1);
        msg.getHeader().setMsgTime(currentTimeMillls);
        msg.getHeader().setLength(body.length());
        msg.setTempReplyBody(body);
        ConcurrentMapCache.getInstance().set(msg.getHeader().getOrderNo(),message.getMessageId(),60*3*1000);
        return bulidBsjCommonReplyMessage(msg);
    }

    public EncodedMessage buildBsjWritePropertyMessage(WritePropertyMessage message, String body){
        BsjMessage msg = new BsjMessage();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMddHHmmss");
        String currentTimeMillls=dateFormat.format(System.currentTimeMillis());
        Map<String,Object> bsjHeader = message.getProperties();
        msg.getHeader().setBeginMark("[");
        msg.getHeader().setDeviceNo(message.getDeviceId());
        msg.getHeader().setIccid(message.getCode());
        msg.getHeader().setOrderNo(bsjHeader.get("orderNo").toString());
        msg.getHeader().setCmd(bsjHeader.get("cmd").toString());
        msg.getHeader().setType(4);
        msg.getHeader().setMsgTime(currentTimeMillls);
        msg.getHeader().setLength(body.length());
        msg.setTempReplyBody(body);
        return bulidBsjCommonReplyMessage(msg);
    }

    private String flowNo(){
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMMddHHmmss");
        String currentTimeMillls=dateFormat.format(System.currentTimeMillis());
        Integer flowInt = flow.getAndIncrement();
        if(flowInt>9999){
            flowInt = 0;
            flow.set(0);
        }
        return String.format("%s%04d",currentTimeMillls,flowInt);

    }

    public static void main(String[] args) throws Exception {
        /*String hex = "494B4D75596E6C4D69524F656D346D7439386E48314B6D726E7236695A536E55464B73516B39663071792B4C6D366235394857445158417A564C4E6F41643954344C637574486E7233526B726B556F4266524F3167476D5434626F6A4F517A526676644C4952436B4D5761465558695A73387342567571455069776661443242";
        byte[] baa = parseHex(hex);
        System.out.println(new String(baa));
        System.out.println(baa);
        if(1==1)return;*/
       //String message = "[866136058688669,89860802162070001815,202205231647230000,DEVICE_LOGIN,4,20220523164724,5,0@0@0]";
        //[866136055799444,89860477012170573202,202203181413300009,GET_HEALTH_INFO,3,20220318141330,1,0]
        String message="[862677060726041,89860477012170573202,202208221633600009,GET_HEALTH_INFO,3,20220822163330,1,0]";
        //862677060140292,89860477012170573202,202208111633300009,GET_HEALTH_INFO,4,20220811094135,1,0
        String encodedText = AesUtils.aes128CbcEncrypt(aesKey,aesIv,message.getBytes());
        System.out.println(encodedText);
        String result = encodedText.replaceAll("[\\s*\t\n\r]", "")+tagAndVersion+suffix;
        System.out.println(result);
        System.out.println(result.getBytes());
//        //加密消息

       /* String msg = "IKMuYnlMiROem4mt98nH1Kmrnr6iZSnUFKsQk9f0qy8tG0cXJZh2JKtu5xj6pKR7Vn9/UCZ+vqrQiYROwufo2gxAr8nejacas8dPlaLUFRG2wo5RwofpVVJUsF1PWgyzDXxuMWrvyVfMReH0mu7M4YAns0jxQ7XqtVmMYIVzNeE=";
        byte[] bbbb= Base64.getDecoder().decode(msg);
        String a = AesUtils.aes128CbcDecrypt(aesKey,aesIv,bbbb);
        System.out.println(a);*/

       // String msg="DRbONIPNT/wm5JAflmw4bUsHD17WXFMaXzBe5hUFlUE3pku4Ej5kBHZCsU9AfxLiU8DSlKIBV9e5DsYqe7YBMlaV97khhrwCuU3VGrfCXCw9pHDp8pKKn31jqiX5TEjrwY92VmmblZrmNTbbSzx36NznxgV79l0mEYdXPhk2ABkgfcJ75pvKfCdx1VVwu4N1bC5OHj5Oj1Dd21Qwa9Ae9gN2BbOm3ydOtPPre6d2wTJF3xp0x+BbB4DQR0FrVDj4RP3FYtu22+RJcapf0Ng2BQ==#kdsjafjalsdjg#170";//"IKMuYnlMiROem4mt98nH1IEgjucVJq+ouaYsUTw2/A5f01f/KtniwOFeYAmmxbkZCBXqdBPwPF+6ubwBJJdYtftBo8+VH8F6NJw5hk+m6DSuoxlit+ktB7dCX8T+c4cO#kdsjafjalsdjg#170";
        String msg="DRbONIPNT/wm5JAflmw4bUsHD17WXFMaXzBe5hUFlUE3pku4Ej5kBHZCsU9AfxLiU8DSlKIBV9e5DsYqe7YBMlaV97khhrwCuU3VGrfCXCxwzpS5rjN3s6GeNBEAJjONTLAJznpixap0878sxzKHDxf8C5N3IhvRUGl5cyzIZLs=#kdsjafjalsdjg#170";
       //BsjMessage bsjMessage=buildBsjMessage(msg);
    }

    public static byte[] parseHex(String hex){
        byte[] result = new byte[hex.length()/2];
        for(int i=0;i<hex.length()/2;i++){
            int high = Integer.parseInt(hex.substring(i*2,i*2+1),16);
            int low = Integer.parseInt(hex.substring(i*2+1,i*2+2),16);
            result[i] = (byte)(high*16+low);
        }
        return result;
    }
}
